
#import <QuartzCore/QuartzCore.h>
#import "FindLampViewController.h"
#import "ChooseEffectViewController.h"
#import "lampmeta.h"
#import "DocumentViewController.h"
#import "HelpViewController.h"
#import "Data.h"
#import "NSString+VoiceOver.h"
#import "UIViewController+ModalWithNavBar.h"
#import "UINavigationItem+InfoButton.h"
#import "SinglePageView.h"

@interface FindLampViewController () <UIScrollViewDelegate, SinglePageViewDelegate, UITableViewDataSource, UITableViewDelegate> {
    CGRect originScrollFrame;
    
    NSMutableSet *visiblePages;
    NSMutableSet *recycledPages;
    
    NSArray *lampList;
    
    BOOL pageControlIsChangingPage;
}

@property (strong, nonatomic) IBOutlet UIScrollView *singleScrollView;
@property (unsafe_unretained, nonatomic) IBOutlet UILabel *captionLabel;
@property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
@property (strong, nonatomic) IBOutlet UITableView *accessibilityTableView;

- (IBAction)valueChangedForPageControl:(id)sender;

@end


@implementation FindLampViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    lampList = [[Data sharedInstance] lampList];
    
    self.pageControl.numberOfPages = lampList.count;
    
    [self.navigationItem addInfoButtonWithTarget:self action:@selector(showInfo)];
    
    visiblePages = [NSMutableSet set];
    recycledPages = [NSMutableSet set];
    
    [self tileSinglePages];
    
    self.captionLabel.text = lampList[self.pageControl.currentPage][kLampItemCaption];
    
    [self.pageControl addTarget:self action:@selector(valueChangedForPageControl:) forControlEvents:UIControlEventValueChanged];

    if (voiceoverEnabled) {
        self.accessibilityTableView.frame = self.view.bounds;
        [self.view addSubview:self.accessibilityTableView];
        self.pageControl.accessibilityElementsHidden = YES;
    }
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
     self.singleScrollView.clipsToBounds = NO;
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    self.singleScrollView.clipsToBounds = YES;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Scroll View Delegate Methods
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (!pageControlIsChangingPage) {
        NSInteger currentPage = self.currentPageForPageControl;
        if (currentPage < lampList.count &&
            self.pageControl.currentPage != currentPage) {
            self.pageControl.currentPage = currentPage;
            [self updateCaptionLabel];
        }
    }
    [self tileSinglePages];
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    self.pageControl.userInteractionEnabled = YES;
    if (pageControlIsChangingPage) {
        [self updateCaptionLabel];
    }
    pageControlIsChangingPage = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self updateCaptionLabel];
}

#pragma mark -
- (void)updateCaptionLabel
{
    self.captionLabel.text = lampList[self.pageControl.currentPage][kLampItemCaption];
}

- (IBAction)valueChangedForPageControl:(id)sender
{
    CGRect frame = self.singleScrollView.frame;
    frame.origin.x = frame.size.width * self.pageControl.currentPage;
    frame.origin.y = 0;
        
    self.pageControl.userInteractionEnabled = NO;
    [self.singleScrollView scrollRectToVisible:frame animated:YES];
    pageControlIsChangingPage = YES;
}

- (NSInteger)currentPageForPageControl
{
    UIScrollView *scrollView = self.singleScrollView;
    CGFloat pageWidth = scrollView.frame.size.width;
    return floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;   
}

- (BOOL)isDisplayingSinglePageForIndex:(NSInteger)index
{
    for (SinglePageView *page in visiblePages) {
        if (page.index == index) {
            return YES;
        }
    }
    return NO;
}

- (SinglePageView *)dequeueRecycledPage
{
    SinglePageView *page = [recycledPages anyObject];
    if (page) {
        [recycledPages removeObject:page];
    }
    return page;
}

- (CGRect)frameForSinglePageAtIndex:(NSInteger)index
{
    CGSize pageSize = self.singleScrollView.bounds.size;
    return CGRectMake(index*pageSize.width, 0, pageSize.width, pageSize.height);
}

- (void)addSinglePageWithIndex:(int)index
{
    SinglePageView *page = [self dequeueRecycledPage];
    if (!page) {
        page = [[SinglePageView alloc] initWithFrame:[self frameForSinglePageAtIndex:index]];
        page.delegate = self;
    } else {
        page.frame = [self frameForSinglePageAtIndex:index];
    }
    NSDictionary *currentLamp = lampList[index];
    page.index = index;
    page.image = [UIImage imageNamed:currentLamp[kLampItemImage]];
    
    [self.singleScrollView addSubview:page];
    page.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
    [visiblePages addObject:page];
}

- (int)currentSinglePageIndex 
{
    return (int)((self.singleScrollView.contentOffset.x / self.singleScrollView.bounds.size.width));
}

- (void) resizeSingleScrollViewContentSize 
{
    self.singleScrollView.contentSize = CGSizeMake(self.singleScrollView.bounds.size.width * ([self currentSinglePageIndex]+2),
                                                   self.singleScrollView.bounds.size.height);
}

- (void)showInfo
{
    HelpViewController *helpVC = [[HelpViewController alloc] initWithNibName:nil bundle:nil];
    helpVC.documentFile = _(@"Socket");
    helpVC.title = _(@"Information");
    [self presentModalWithNavBar:helpVC];
}

#define kHistoryCountForSinglePages 5
- (void) tileSinglePages
{
    CGRect visibleBounds = self.singleScrollView.bounds;
    int firstNeededSinglePageIndex = floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds));
    int lastNeededSinglePageIndex  = floorf((CGRectGetMaxX(visibleBounds)-1) / CGRectGetWidth(visibleBounds));
    firstNeededSinglePageIndex = MAX(0, firstNeededSinglePageIndex - kHistoryCountForSinglePages);
    lastNeededSinglePageIndex  = MAX(1, lastNeededSinglePageIndex + 1);
    
    // Recycle unneeded views
    for (SinglePageView *page in visiblePages) {
        if (page.index < firstNeededSinglePageIndex || page.index > lastNeededSinglePageIndex) {
            [recycledPages addObject:page];
            [page removeFromSuperview];
        }
    }
    [visiblePages minusSet:recycledPages];
    
    if (lastNeededSinglePageIndex < lampList.count) {
        // Add missing pages
        for (int i = firstNeededSinglePageIndex; i <= lastNeededSinglePageIndex; i++) {
            if (![self isDisplayingSinglePageForIndex:i]) {
                [self addSinglePageWithIndex:i];
            }
        }
        [self resizeSingleScrollViewContentSize];
    }

    // Cover flow fade out
    CGFloat viewWidth_2 = self.singleScrollView.frame.size.width / 2;
    for (SinglePageView *page in visiblePages) {
        CGFloat visualCenter = self.singleScrollView.contentOffset.x + viewWidth_2;
        CGFloat delta = page.center.x - visualCenter;
        CGFloat k = ABS(delta) / 200;
        page.alpha = k < 1 ? 1 - k * k * k : 0;
    }
}

#pragma mark - Single Page View Delegate
- (void)didTapOnSinglePageWithIndex:(NSUInteger)index
{
    NSDictionary *currentLamp = lampList[index];
    
    NSAssert((currentLamp[kLampItemEffects] != nil) != (currentLamp[kLampItemDocument] != nil),
             @"Error in data; effects and document at the same time is not allowed");
    
    if (currentLamp[kLampItemEffects]) {
        ChooseEffectViewController *cEVC = [[ChooseEffectViewController alloc] initWithNibName:nil bundle:nil];
        cEVC.lampItem = currentLamp;
        [self.navigationController pushViewController:cEVC animated:YES];
        
    } else if (currentLamp[kLampItemDocument]) {
        DocumentViewController *detailVC = [[DocumentViewController alloc] initWithNibName:nil bundle:nil];
        [detailVC showDocumentWithName:currentLamp[kLampItemDocument]];
        detailVC.backButtonTitle = _(@"Välj lampa");
        detailVC.title = currentLamp[@"caption"];
        [self.navigationController pushViewController:detailVC animated:YES];
    }
}

#pragma mark - Table view datasource

#define kNibName @"InformationCell"

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return lampList.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kNibName];
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kNibName];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        cell.textLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:17];
    }
    cell.textLabel.text = lampList[indexPath.row][kLampItemCaption];
    cell.textLabel.accessibilityLabel = [cell.textLabel.text stringByOptimizingForVoiceOver];
    
	return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *currentLamp = lampList[indexPath.row];
    
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    if (currentLamp[kLampItemDocument]) {
        DocumentViewController *detailVC = [[DocumentViewController alloc] initWithNibName:nil bundle:nil];
        [detailVC showDocumentWithName:currentLamp[kLampItemDocument]];
        detailVC.backButtonTitle = _(@"Välj lampa");
        detailVC.title = currentLamp[@"caption"];
        [self.navigationController pushViewController:detailVC animated:YES];
    } else {
        ChooseEffectViewController *cEVC = [[ChooseEffectViewController alloc] initWithNibName:nil bundle:nil];
        cEVC.lampItem = currentLamp;
        [self.navigationController pushViewController:cEVC animated:YES];
    }
}

@end
